
#include "Shm.h"

void DEBUGPrint();
Shm::Shm():m_pcFileName(NULL),m_hMapFile(INVALID_HANDLE_VALUE),m_hFile(INVALID_HANDLE_VALUE),m_pBuf(NULL),m_pBufAllocation(NULL)    
{
}
Shm::~Shm()
{
    close();
} 
void Shm::close()
{
#if defined   __linux__
    if (NULL != m_pBuf)
    {
        if (munmap(m_pBuf, nMaxMappedFileSize) == -1) 
        {
            DEV;
        }
    }
    if (INVALID_HANDLE_VALUE !=m_hFile)
    {
        ::close(m_hMapFile); // close the file mapping object
    }
    if(NULL != m_pcFileName) 
    {
        int iRet = unlink (m_pcFileName);
        if (iRet== 0)
        {
            cout<<"Removing map file." <<endl;
        }
    }

#elif defined _WIN32 || defined _WIN64
    if (NULL != m_pBuf)
    {
        UnmapViewOfFile(m_pBuf);
    }
    if (INVALID_HANDLE_VALUE != m_hMapFile)
    {
        CloseHandle(m_hMapFile); // close the file mapping object
    }
    if (INVALID_HANDLE_VALUE !=m_hFile)
    {
        CloseHandle(m_hFile); // close the file mapping object
    }

    if(NULL != m_pcFileName)
    {
        int iRet = DeleteFile((LPCWSTR)m_pcFileName);
        if (iRet > 0)
        {
            cout<<"Removing map file." <<endl;
        }
    }

#endif
}
HANDLE Shm::OpenOrCreateFile(const char* pcFileName )
{

    HANDLE hFile = INVALID_HANDLE_VALUE;
#if defined   __linux__
#elif defined _WIN32 || defined _WIN64

    wchar_t  wcstring[256];
    size_t convertedChars = 0,newsize = strlen(pcFileName) + 1;;
    mbstowcs_s(&convertedChars, wcstring, newsize, pcFileName, _TRUNCATE);

    hFile = CreateFile(wcstring, //lpFileName
        GENERIC_READ | GENERIC_WRITE,//dwDesiredAccess
        FILE_SHARE_WRITE | FILE_SHARE_READ,////dwShareMode
        NULL,//lpSecurityAttributes
        OPEN_EXISTING,//dwCreationDisposition
        FILE_ATTRIBUTE_NORMAL,//dwFlagsAndAttributes
        NULL //hTemplateFile
        );
    if (INVALID_HANDLE_VALUE != hFile)
    {
        cout<<"Opening existing mapped file."<<endl;
        return hFile;
    }
    else if (INVALID_HANDLE_VALUE == hFile)
    {
        cout<<"Mapped file not present." <<endl;
        hFile = CreateFile(wcstring,
            GENERIC_READ | GENERIC_WRITE,//dwDesiredAccess
            FILE_SHARE_WRITE | FILE_SHARE_READ,////dwShareMode
            NULL,
            CREATE_NEW,
            FILE_ATTRIBUTE_NORMAL,
            NULL);

        if (INVALID_HANDLE_VALUE != hFile)
        {
            cout<<"Mapped file created." <<endl;
        }
        return hFile;
    }
#endif
    return hFile;
}
bool Shm::OpenMappedFileReader(const char*pcFileName)

{
    bool bStat = false;
    do
    {
#if defined   __linux__
        int nFD = open(pcFileName, //path
            O_RDWR,//flags
            S_IRUSR| S_IWUSR ); //mode
        if (-1  == nFD)
        {
            break;
        }
        if (lseek(nFD,//file descriptor
            nMaxMappedFileSize - 1,//offset
            SEEK_SET) // whence);
            == -1)
        {
            break;
        }
        m_hFile = nFD;
#elif defined _WIN32 || defined _WIN64
        wchar_t  wcstring[256];
        size_t convertedChars = 0,newsize = strlen(pcFileName) + 1;;
        mbstowcs_s(&convertedChars, wcstring, newsize, pcFileName, _TRUNCATE);    
        HANDLE hFile = CreateFile(wcstring,
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_WRITE | FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL);
        if (INVALID_HANDLE_VALUE != hFile)
        {
            cout<<"Opening existing mapped file."<<endl;
        }
        else
        {
            DEV;
            break;
        }
        m_hFile = hFile;

        m_hMapFile = CreateFileMapping( m_hFile,
            NULL, // default security
            PAGE_READWRITE, // read/write permission
            0, // size of mapping object, high
            nMaxMappedFileSize, // size of mapping object, low
            NULL); // name of mapping object

        if (m_hMapFile == NULL)
        {
            DEV;
            break;
        }
#endif
        m_pcFileName = (char*)pcFileName;
        cout<< "File mapping object successfully opened for reading."<<endl;
        bStat = true;
    } while(0);
    if (false == bStat)
    {
        DEBUGPrint();
    }
    return bStat;
}
bool Shm::OpenMappedFileWriter(const char*pcFileName)
{
    bool bStat = false;
    do
    {
#if defined   __linux__
        int nFD = open(pcFileName, //path
            O_RDWR| O_CREAT,//flags
            S_IRUSR| S_IWUSR ); //mode
        if (-1  == nFD)
        {
            break;
        }
        if (lseek(nFD,//file descriptor
            nMaxMappedFileSize - 1,//offset
            SEEK_SET) // whence);
            == -1)
        {
            break;
        }
        m_hFile = nFD;
        write (nFD, "", 1);
#elif defined _WIN32 || defined _WIN64
        HANDLE hFile = OpenOrCreateFile(pcFileName);
        if (INVALID_HANDLE_VALUE == hFile )
        {
            break;
        }
        m_hFile = hFile;
        m_hMapFile = CreateFileMapping( m_hFile,
            NULL, // default security
            PAGE_READWRITE, // read/write permission
            0, // size of mapping object, high
            nMaxMappedFileSize, // size of mapping object, low
            NULL); // name of mapping object

        if (m_hMapFile == NULL)
        {
            break;
        }
#endif
        m_pcFileName = (char*)pcFileName;
        cout<< "File mapping object successfully created for writing."<<endl;
        bStat = true;
    }
    while(0);
    if (false == bStat )
    {
        DEBUGPrint();
    }
    return bStat;
}
bool Shm::init(const char * pcFileName, QMode eMode)
{
    bool bStat = false;
    do
    {
        if ( eWriter == eMode )
        {
            bStat = OpenMappedFileWriter(pcFileName);
        }
        else if ( eReader  == eMode )
        {
            bStat = OpenMappedFileReader(pcFileName);
        }
        else
        {
            break;
        }
        if (false == bStat)
        {
            break;
        }

#if defined   __linux__

        m_pBuf = mmap(NULL, nMaxMappedFileSize, (PROT_READ| PROT_WRITE),  MAP_SHARED, m_hFile, 0); 
        //void *addr, size_t length, int prot, int flags,int fd, off_t offset
        if (MAP_FAILED == m_pBuf) 
        {
            break;           
        }
        m_pBufAllocation = m_pBuf;
#elif defined _WIN32 || defined _WIN64

        m_pBuf = (void*) MapViewOfFile(m_hMapFile, //hFileMappingObject
            FILE_MAP_ALL_ACCESS, //dwDesiredAccess
            0,//dwFileOffsetHigh
            0,//dwFileOffsetLow
            nNumberOfBytesToMap); //dwNumberOfBytesToMap

        if (m_pBuf == NULL)
        {
            break;
        }
	m_pBufAllocation = m_pBuf;
#endif
        bStat = true;
    } while(0);
    return bStat;
}

